﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Locator.Silverlight.Client.Models.StoresServiceReference;
using System.Collections.Generic;
using Locator.Silverlight.Client.Models.ViewModels.Elements;

namespace Locator.Silverlight.Client.Models
{
    public class StoreModel : ModelBase<IStoresServiceAsync>, IStoreModel
    {
        /// <summary>
        /// Initializes a new instance of the StoreModel class.
        /// </summary>
        public StoreModel()
            : this(new StoresServiceClient("BasicHttpBinding_IStoresService"))
        {

        }

        public StoreModel(IStoresServiceAsync service)
            : base(service)
        {
            
        }

        #region IStoreModel Members

        public void GetPersonalLocationsForCurrentUserAsync(Action<List<PersonalLocationViewModel>, Exception> callback)
        {
            this.Service.GetPersonalLocationsForCurrentUserCompleted += (source, eventArgs) =>
            {
                if (eventArgs.Error == null)
                {
                    var personalLocationViewModelList = new List<PersonalLocationViewModel>();
                    foreach (var personalLocation in eventArgs.Result)
                    {
                        PersonalLocationViewModel viewModel = new PersonalLocationViewModel()
                        {
                            Description = personalLocation.Description,
                            Id = personalLocation.Id,
                            Latitude = personalLocation.Latitude,
                            Longitude = personalLocation.Longitude
                        };

                        personalLocationViewModelList.Add(viewModel);
                    }

                    callback(personalLocationViewModelList, null);
                }
                else
                {
                    callback(null, eventArgs.Error);
                }
            };

            this.Service.GetPersonalLocationsForCurrentUserAsync();
        }

        public void FindStoresByPostalCodeAsync(string postalCode, int radiusInKm, Action<List<StoreViewModel>, Exception> callback)
        {
            this.Service.FindStoresByPostalCodeCompleted += (source, eventArgs) =>
            {
                if (eventArgs.Error == null)
                {
                    callback(CreateStoreViewModelList(eventArgs.Result), null);
                }
                else
                {
                    callback(null, eventArgs.Error);
                }
            };

            this.Service.FindStoresByPostalCodeAsync(postalCode, radiusInKm);
        }
   
        public void FindStoresByLatitudeAndLongitudeAsync(decimal latitude, decimal longitude, int radiusInKm, Action<List<StoreViewModel>, Exception> callback)
        {
            this.Service.FindStoresByLatitudeAndLongitudeCompleted += (source, eventArgs) =>
            {
                if (eventArgs.Error == null)
                {
                    callback(CreateStoreViewModelList(eventArgs.Result), null);
                }
                else
                {
                    callback(null, eventArgs.Error);
                }
            };

            this.Service.FindStoresByLatitudeAndLongitudeAsync(latitude, longitude, radiusInKm);
        }

        public void FindStoresByPersonalLocationAsync(int personalLocationId, int radiusInKm, Action<List<StoreViewModel>, Exception> callback)
        {
            this.Service.FindStoresByPersonalLocationCompleted += (source, eventArgs) =>
            {
                if (eventArgs.Error == null)
                {
                    callback(CreateStoreViewModelList(eventArgs.Result), null);
                }
                else
                {
                    callback(null, eventArgs.Error);
                }
            };

            this.Service.FindStoresByPersonalLocationAsync(personalLocationId, radiusInKm);
        }

        public void GetStoresForCurrentUserAsync(Action<List<StoreViewModel>, Exception> callback)
        {
            this.Service.GetStoresForCurrentUserCompleted += (source, eventArgs) =>
            {
                if (eventArgs.Error == null)
                {
                    callback(CreateStoreViewModelList(eventArgs.Result), null);
                }
                else
                {
                    callback(null, eventArgs.Error);
                }
            };

            this.Service.GetStoresForCurrentUserAsync();
        }

        public void FindStoresNotUsedByCurrentUserAsync(Action<List<StoreViewModel>, Exception> callback)
        {
            this.Service.BeginFindStoresNotUsedByCurrentUser(asyncState =>
            {
                try
                {
                    var storeCollection = this.Service.EndFindStoresNotUsedByCurrentUser(asyncState);
                    callback(CreateStoreViewModelList(storeCollection), null);
                }
                catch (Exception ex)
                {
                    callback(null, ex);
                }
            }, null);
        }

        public void AllCitiesAsync(Action<List<CityViewModel>, Exception> callback)
        {
            this.Service.AllCitiesCompleted += (source, eventArgs) =>
            {
                if (eventArgs.Error == null)
                {
                    var cityViewModelList = new List<CityViewModel>();
                    foreach (var city in eventArgs.Result)
                    {
                        cityViewModelList.Add(new CityViewModel(city));
                    }

                    callback(cityViewModelList, null);
                }
                else
                {
                    callback(null, eventArgs.Error);
                }
            };

            this.Service.AllCitiesAsync();
        }

        public void FindStoresInCityAsync(string cityName, Action<List<StoreViewModel>, Exception> callback)
        {
            this.Service.FindStoresInCityCompleted += (source, eventArgs) =>
            {
                if (eventArgs.Error == null)
                {
                    callback(CreateStoreViewModelList(eventArgs.Result), null);
                }
                else
                {
                    callback(null, eventArgs.Error);
                }
            };

            this.Service.FindStoresInCityAsync(cityName);
        }

        public void AddStoreForCurrentUserAsync(UserStoreViewModel store, Action<Exception> callback)
        {
            this.Service.AddStoreForCurrentUserCompleted += (source, eventArgs) =>
            {
                if (eventArgs.Error == null)
                {
                    callback(null);
                }
                else
                {
                    callback(eventArgs.Error);
                }
            };

            this.Service.AddStoreForCurrentUserAsync(store.Store.Id);
        }

        public void DeleteStoreForCurrentUserAsync(StoreViewModel store, Action<Exception> callback)
        {
            this.Service.DeleteStoreForCurrentUserCompleted += (source, eventArgs) =>
            {
                if (eventArgs.Error == null)
                {
                    callback(null);
                }
                else
                {
                    callback(eventArgs.Error);
                }
            };

            this.Service.DeleteStoreForCurrentUserAsync(store.Id);
        }

        #endregion

        private static List<StoreViewModel> CreateStoreViewModelList(IEnumerable<Store> stores)
        {
            var storeViewModelList = new List<StoreViewModel>();
            foreach (var store in stores)
            {
                StoreViewModel newStoreViewModel = new StoreViewModel() { Id = store.Id, Latitude = store.Latitude, Longitude = store.Longitude };
                newStoreViewModel.SetAddress(store.Address, store.City);
                storeViewModelList.Add(newStoreViewModel);
            }

            return storeViewModelList;
        }
    }
}
